package jmine.tec.hydra.domain.actions;

import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

import jmine.tec.hydra.api.HydraAction;
import jmine.tec.hydra.api.HydraMessage;
import jmine.tec.hydra.api.MessageActivationAction;
import jmine.tec.hydra.api.MessageDirection;
import jmine.tec.hydra.api.ReceiveMessageAction;
import jmine.tec.hydra.domain.HydraSystem;
import jmine.tec.hydra.receive.impl.mq.HydraMessageListener;
import jmine.tec.persist.annotation.DiscriminatorComment;
import bancosys.tec.datadigester.input.ResetableInputStreamFactory;

/**
 * HydraAction responsável por ler e armazenar uma mensagem propriamente e encaminhar para decodificação.
 * 
 * @author lundberg
 */
@Entity
@DiscriminatorValue("0")
@DiscriminatorComment("RECEBIMENTO")
public class DefaultReceiveMessageAction extends AbstractHydraAction implements ReceiveMessageAction {

    // Atributos transientes, existem apenas na criação da action e deixam de existir uma vez que a mensagem foi armazenada com sucesso.
    private HydraSystem system;

    private InputStream input;

    private Map<String, String> messageProperties;

    /**
     * {@inheritDoc}
     */
    public ReceiveMessageAction prepare(HydraSystem sys, InputStream in, Map<String, String> properties) {
        this.input = in;
        this.system = sys;
        this.messageProperties = properties;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected List<HydraAction> doExecute() throws Exception {
        LOGGER.debug("Iniciando leitura da mensagem.");
        this.setSystem(this.system);
        InputStream resetableInput = ResetableInputStreamFactory.createResetableInputStream(this.input);
        final HydraMessage message =
                this.getController().getProvider()
                        .createMessage(this.getRequest(), MessageDirection.RECEIVED, resetableInput, this.messageProperties);
        this.saveMessage(message);
        LOGGER.debug("Mensagem lida e salva com sucesso, criando action de decodificação.");
        MessageActivationAction activation = this.getController().getProvider().createAction(MessageActivationAction.class);
        activation.prepare(message);
        this.logAsSystem("Mensagem recebida armazenada e enviada para decodificação.");
        if (message.getProperties() != null && message.getProperties().containsKey(HydraMessageListener.MESSAGE_PUT_TIMESTAMP)) {
            this.logAsSystem("Data/hora de postagem: " + message.getProperties().get(HydraMessageListener.MESSAGE_PUT_TIMESTAMP));
        }
        return Collections.singletonList((HydraAction) activation);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String createDescription() {
        return "Recebimento de mensagem";
    }
}
